home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / drivers.arc / TAIL.ASM < prev    next >
Encoding:
Assembly Source File  |  1988-10-20  |  7.5 KB  |  366 lines

  1. ;/* PC/FTP Packet Driver source, conforming to version 1.05 of the spec
  2. ;*  Russell Nelson, Clarkson University.  July 20, 1988
  3. ;*  Portions (C) Copyright 1988 Russell Nelson
  4. ;*
  5. ;*  Permission is granted to any individual or institution to use, copy,
  6. ;*  modify, or redistribute this software and its documentation provided
  7. ;*  this notice and the copyright notices are retained.  This software may
  8. ;*  not be distributed for profit, either in original form or in derivative
  9. ;*  works.  Russell Nelson makes no representations about the suitability
  10. ;*  of this software for any purpose.  RUSSELL NELSON GIVES NO WARRANTY,
  11. ;*  EITHER EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION
  12. ;*  PROVIDED, INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY
  13. ;*  AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  14. ;*/
  15.  
  16.  
  17. code    segment byte public
  18.     assume    cs:code, ds:code
  19.  
  20.     extrn    phd_dioa: byte
  21.     extrn    phd_environ: word
  22.  
  23. ;usage_msg is of the form "usage: driver <packet_int_no> <args>"
  24.     extrn    usage_msg: byte
  25.  
  26. ;copyright_msg is of the form:
  27. ;"Packet driver for the foobar",CR,LF
  28. ;"Portions Copyright 19xx, J. Random Hacker".
  29.     extrn    copyright_msg: byte
  30.  
  31. copyleft_msg    db    "Packet driver skeleton copyright 1988, Russell Nelson.",CR,LF
  32.         db    "Don't pretend that you wrote it, and don't try to make money off of it.",CR,LF,'$'
  33.  
  34. ;parse_args should parse the arguments.
  35. ;called with ds:si -> immediately after the packet_int_no.
  36.     extrn    parse_args: near
  37.  
  38.     extrn    our_isr: near, their_isr: dword
  39.     extrn    packet_int_no: byte
  40.     extrn    is_at: byte
  41.     extrn    int_no: byte
  42.  
  43. packet_int_no_name    db    "Packet interrupt number ",'$'
  44.  
  45. signature    db    'PKT DRVR',0
  46. signature_len    equ    $-signature
  47.  
  48. already_msg    db    "There is already a packet driver at that address",'$'
  49.  
  50. ;etopen should initialize the device.  If it needs to give an error, it
  51. ;can issue the error message and quit to dos.
  52.     extrn    etopen: near
  53.  
  54. segmoffs    struc
  55. offs        dw    ?
  56. segm        dw    ?
  57. segmoffs    ends
  58.  
  59. HT    equ    09h
  60. CR    equ    0dh
  61. LF    equ    0ah
  62.  
  63. already_error:
  64.     mov    dx,offset already_msg
  65.     jmp    short error
  66. usage_error:
  67.     mov    dx,offset usage_msg
  68. error:
  69.     mov    ah,9
  70.     int    21h
  71.     int    20h
  72.  
  73.     public    start_1
  74. start_1:
  75.     mov    dx,offset copyright_msg
  76.     mov    ah,9
  77.     int    21h
  78.  
  79.     mov    dx,offset copyleft_msg
  80.     mov    ah,9
  81.     int    21h
  82.  
  83.     mov    si,offset phd_dioa+1
  84.     cmp    byte ptr [si],CR    ;end of line?
  85.     je    usage_error
  86.  
  87.     mov    di,offset packet_int_no    ;parse the packet interrupt number
  88.     mov    bx,offset packet_int_no_name
  89.     call    get_number        ;  for them.
  90.  
  91.     call    parse_args
  92.  
  93.     mov    ah,35h            ;get their packet interrupt.
  94.     mov    al,packet_int_no
  95.     int    21h
  96.  
  97.     lea    di,3[bx]        ;see if there is already a signature there.
  98.     mov    si,offset signature
  99.     mov    cx,signature_len
  100.     repe    cmpsb
  101.     je    already_error        ;yes, so we can't go there.
  102.  
  103.     mov    ax,0f000h        ;ROM segment
  104.     mov    es,ax
  105.     cmp    word ptr es:[0fffeh],0fch    ;is this an AT?
  106.     jne    not_at            ;no.
  107.  
  108.     inc    is_at            ;yes - remember that we've got an AT.
  109.  
  110.     cmp    int_no,2        ;map IRQ 2 to IRQ 9.
  111.     jne    not_at
  112.     mov    int_no,9
  113. not_at:
  114.  
  115.     call    etopen            ;init the driver.  If any errors,
  116.                     ;this routine returns cy.
  117.     jc    no_resident
  118.  
  119.     push    dx            ;remember where they want to end.
  120.  
  121.     mov    ah,35h            ;remember their packet interrupt.
  122.     mov    al,packet_int_no
  123.     int    21h
  124.     mov    their_isr.offs,bx
  125.     mov    their_isr.segm,es
  126.  
  127.     mov    ah,25h            ;install our packet interrupt
  128.     mov    dx,offset our_isr
  129.     int    21h
  130.  
  131.     mov    ah,49h            ;free our environment, because
  132.     mov    es,phd_environ        ;  we won't need it.
  133.     int    21h
  134.  
  135.     mov    bx,1            ;get the stdout handle.
  136.     mov    ah,3eh            ;close it in case they redirected it.
  137.     int    21h
  138.  
  139.     pop    dx            ;get their ending address.
  140.     add    dx,0fh            ;round up to next highest paragraph.
  141.     mov    cl,4
  142.     shr    dx,cl
  143.     mov    ah,31h            ;terminate, stay resident.
  144.     int    21h
  145.  
  146. no_resident:
  147.     int    20h
  148.  
  149.  
  150.     public    get_number
  151. get_number:
  152.     mov    bp,10            ;we default to 10.
  153.     jmp    short get_number_0
  154.  
  155.     public    get_hex
  156. get_hex:
  157.     mov    bp,16
  158. ;get a hex number from [si], skipping leading blanks.
  159. ;return cy if there are no digits at all.
  160. ;return nc, bx:cx = number, and store cx at [di]
  161. get_number_0:
  162.     push    bx            ;remember the name of this number.
  163.     call    skip_blanks
  164.     call    get_digit        ;is there really a number here?
  165.     jc    get_number_3
  166.     or    al,al            ;Does the number begin with zero?
  167.     jne    get_number_4        ;no.
  168.     mov    bp,8            ;yes - they want octal.
  169. get_number_4:
  170.  
  171.     xor    cx,cx            ;get a hex number.
  172.     xor    bx,bx
  173. get_number_1:
  174.     lodsb
  175.     cmp    al,'x'            ;did they really want hex?
  176.     je    get_number_5        ;yes.
  177.     cmp    al,'X'            ;did they really want hex?
  178.     je    get_number_5        ;yes.
  179.     call    get_digit        ;convert a character into an int.
  180.     jc    get_number_2        ;not a digit (neither hex nor dec).
  181.     xor    ah,ah
  182.     cmp    ax,bp            ;larger than our base?
  183.     jae    get_number_2        ;yes.
  184.  
  185.     push    ax            ;save the new digit.
  186.  
  187.     mov    ax,bp            ;multiply the low word by ten.
  188.     mul    cx
  189.     mov    cx,ax            ;keep the low word.
  190.     push    dx            ;save the high word for later.
  191.     mov    ax,bp
  192.     mul    bx
  193.     mov    bx,ax            ;we keep only the low word (which is our high word)
  194.     pop    dx
  195.     add    bx,ax            ;add the high result from earlier.
  196.  
  197.     pop    ax            ;get the new digit back.
  198.     add    cx,ax            ;add the new digit in.
  199.     adc    bx,0
  200.     jmp    get_number_1
  201. get_number_5:
  202.     mov    bp,16            ;change the base to hex.
  203.     jmp    get_number_1
  204. get_number_2:
  205.     dec    si
  206.     mov    [di],cx            ;store the parsed number.
  207.     mov    [di+2],bx
  208.     clc
  209.     jmp    short get_number_6
  210. get_number_3:
  211.     stc
  212. get_number_6:
  213.     pop    dx            ;get the name of the number back.
  214.  
  215.     pushf                ;save some stuff.
  216.     push    bx
  217.     push    cx
  218.     push    si
  219.     push    di
  220.     mov    ah,9            ;print the name of the number.
  221.     int    21h
  222.     mov    al,'0'
  223.     call    chrout
  224.     mov    al,'x'
  225.     call    chrout
  226.     mov    ax,[di]            ;print the number in hex.
  227.     mov    dx,[di+2]
  228.     call    hexout
  229.     mov    al,' '
  230.     call    chrout
  231.     mov    al,'('
  232.     call    chrout
  233.     mov    ax,[di]            ;print the number in decimal.
  234.     mov    dx,[di+2]
  235.     call    decout
  236.     mov    al,')'
  237.     call    chrout
  238.     mov    al,CR
  239.     call    chrout
  240.     mov    al,LF
  241.     call    chrout
  242.     pop    di
  243.     pop    si
  244.     pop    cx
  245.     pop    bx
  246.     popf
  247.     ret
  248.  
  249.  
  250.     public    skip_blanks
  251. skip_blanks:
  252.     lodsb                ;skip blanks.
  253.     cmp    al,' '
  254.     je    skip_blanks
  255.     cmp    al,HT
  256.     je    skip_blanks
  257.     dec    si
  258.     ret
  259.  
  260.  
  261. get_digit:
  262. ;enter with al = character
  263. ;return nc, al=digit, or cy if not a digit.
  264.     cmp    al,'0'            ;decimal digit?
  265.     jb    get_digit_1        ;no.
  266.     cmp    al,'9'            ;. .?
  267.     ja    get_digit_2        ;no.
  268.     sub    al,'0'
  269.     clc
  270.     ret
  271. get_digit_2:
  272.     or    al,20h
  273.     cmp    al,'a'            ;hex digit?
  274.     jb    get_digit_1
  275.     cmp    al,'f'            ;hex digit?
  276.     ja    get_digit_1
  277.     sub    al,'a'-10
  278.     clc
  279.     ret
  280. get_digit_1:
  281.     stc
  282.     ret
  283.  
  284.  
  285.     public    hexout
  286. hexout:
  287.     mov    cl,'0'            ;prepare to eliminate leading zeroes.
  288.     xchg    ax,dx            ;just output 32 bits in hex.
  289.     call    wordout            ;output dx.
  290.     xchg    ax,dx
  291.     jmp    wordout            ;output ax.
  292.  
  293.     public    decout
  294. decout:
  295.     mov    si,ax            ;get the number where we want it.
  296.     mov    di,dx
  297.  
  298.     xor    ax,ax            ;start with all zeroes in al,bx,bp
  299.     mov    bx,ax
  300.     mov    bp,ax
  301.  
  302.     mov    cx,32            ;32 bits in two 16 bit registers.
  303. decout_1:
  304.     shl    si,1
  305.     rcl    di,1
  306.     xchg    bp,ax
  307.     call    addbit
  308.     xchg    bp,ax
  309.     xchg    bx,ax
  310.     call    addbit
  311.     xchg    bx,ax
  312.     adc    al,al
  313.     daa
  314.     loop    decout_1
  315.  
  316.     mov    cl,'0'            ;prepare to eliminate leading zeroes.
  317.     call    byteout            ;output the first two.
  318.     mov    ax,bx            ;output the next four
  319.     call    wordout            ;output the next four
  320.     mov    ax,bp
  321. wordout:
  322.     push    ax
  323.     mov    al,ah
  324.     call    byteout
  325.     pop    ax
  326. byteout:
  327.     mov    ah,al
  328.     shr    al,1
  329.     shr    al,1
  330.     shr    al,1
  331.     shr    al,1
  332.     call    digout
  333.     mov    al,ah
  334. digout:
  335.     and    al,0fh
  336.     add    al,90h    ;binary digit to ascii hex digit.
  337.     daa
  338.     adc    al,40h
  339.     daa
  340.     cmp    al,cl            ;leading zero?
  341.     je    return
  342.     mov    cl,-1            ;no more leading zeros.
  343. chrout:
  344.     push    ax            ;print the char in al.
  345.     xchg    al,dl
  346.     mov    ah,2
  347.     int    21h
  348.     xchg    al,dl
  349.     pop    ax
  350. return:
  351.     ret
  352.  
  353.  
  354. addbit:    adc    al,al
  355.     daa
  356.     xchg    al,ah
  357.     adc    al,al
  358.     daa
  359.     xchg    al,ah
  360.     ret
  361.  
  362.  
  363. code    ends
  364.  
  365.     end
  366.